#include "StdDevice_I2C.h"
#include "StdDevice_common.h"

static pika_dev* _get_dev(PikaObj* self) {
    pika_dev* dev = PIKA_HAL_OBJ2DEV(self);
    if (NULL != dev) {
        return dev;
    }
    dev = pika_hal_open(PIKA_HAL_IIC, obj_getStr(self, "name"));
    if (NULL == dev) {
        obj_setErrorCode(self, PIKA_RES_ERR_RUNTIME_ERROR);
        obj_setSysOut(self, "[ERROR] open I2C '%s' failed.",
                          obj_getStr(self, "name"));
        return NULL;
    }
    obj_setPtr(self, "pika_dev", dev);
    return dev;

}
static void _free_dev(pika_dev* dev){
    if (NULL != dev && NULL != dev->ioctl_config) {
        pikaFree(dev->ioctl_config, sizeof(pika_hal_IIC_config));
        dev->ioctl_config = NULL;
    }
    if (NULL != dev) {
        pikaFree(dev, sizeof(pika_dev));
    }
}

void StdDevice_I2C___init__(PikaObj *self, char* name){
    obj_setPtr(self, "pika_dev", NULL);
    obj_setStr(self, "name", name);
}
void StdDevice_I2C_open(PikaObj *self, int speed){
    pika_dev* dev = _get_dev(self);
    pika_hal_IIC_config cfg = {0};
    cfg.speed = speed;
    cfg.master_or_slave = 
    pika_hal_ioctl(dev, PIKA_HAL_IOCTL_CONFIG, &cfg);
}
void StdDevice_I2C_close(PikaObj *self){
    pika_dev* dev = _get_dev(self);
    pika_hal_SPI_config* cfg_ptr = dev->platform_data;
    pika_hal_ioctl(dev, PIKA_HAL_IOCTL_DISABLE);
    pika_hal_close(dev);
    obj_setPtr(self, "pika_dev", NULL);
}   
char* StdDevice_I2C_get_name(PikaObj *self){
    return obj_getStr(self, "name");
}
void StdDevice_I2C_write(PikaObj *self, uint8_t* data, int length){
    pika_dev* dev = _get_dev(self);
    int res = pika_hal_write(dev, data, length);
    if (res < 0){
        obj_setErrorCode(self, PIKA_RES_ERR_RUNTIME_ERROR);
        obj_setSysOut(self, "[ERROR] write fail.");
        return;
    }
}
Arg* StdDevice_I2C_read(PikaObj *self, int length){
    pika_dev* dev = _get_dev(self);
    uint8_t* data = (uint8_t*)pikaMalloc(length+1);
    if (NULL == data) {
        obj_setErrorCode(self, PIKA_RES_ERR_RUNTIME_ERROR);
        obj_setSysOut(self, "[ERROR] not enough memory.");
        return NULL;
    }
    int ret = pika_hal_read(dev, data, length);
    if (ret < 0) {
        pikaFree(data, length);
        obj_setErrorCode(self, PIKA_RES_ERR_RUNTIME_ERROR);
        obj_setSysOut(self, "[ERROR] SPI read fail.");
        return NULL;
    }
    Arg* res = arg_newBytes(data, length);
    pikaFree(data, length+1);
    return res;
}
void StdDevice_I2C_remap(PikaObj *self, char* sda_name, char* scl_name){
    pika_dev* dev = _get_dev(self);
    pika_hal_IIC_config cfg_cb = {0};

    pika_dev* sda_dev  = pika_hal_open(PIKA_HAL_GPIO, sda_name);
    if (sda_dev == NULL){
        obj_setErrorCode(self, PIKA_RES_ERR_RUNTIME_ERROR);
        obj_setSysOut(self, "[ERROR] open '%s' failed.", sda_name);
        return;
    }
    pika_dev* scl_dev = pika_hal_open(PIKA_HAL_GPIO, scl_name);
    if (scl_dev == NULL){
        _free_dev(sda_dev);
        obj_setErrorCode(self, PIKA_RES_ERR_RUNTIME_ERROR);
        obj_setSysOut(self, "[ERROR] open '%s' failed.", scl_name);
        return;
    }

    pika_hal_ioctl(dev, PIKA_HAL_IOCTL_CONFIG, &cfg_cb);

    _free_dev(sda_dev);
    _free_dev(scl_dev);
}
void StdDevice_I2C___del__(PikaObj *self){
    pika_dev* dev = PIKA_HAL_OBJ2DEV(self);
    if (NULL != dev && NULL != dev->ioctl_config) {
        pikaFree(dev->ioctl_config, sizeof(pika_hal_IIC_config));
        dev->ioctl_config = NULL;
    }
    if (NULL != dev) {
        pikaFree(dev, sizeof(pika_dev));
    }
}